﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using DTBuilderLib.VisualHierarchyClasses;
using System.Drawing;

namespace t_DTBuilderLib
{
    /// <summary>
    /// Test the Visual holder class -- which holds onto several different visual image classes.
    /// </summary>
    [TestClass]
    public class t_VisualHolder
    {
        public t_VisualHolder()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void VisualHolderNoImage()
        {
            VisualHolder_Accessor c = new VisualHolder_Accessor();
            Assert.IsTrue(c.Width == 0, "Width is not zero for contentless visual holder");
            Assert.IsTrue(c.Height == 0, "Height is not zero for contentless visual holder");
            Assert.IsTrue(c.XPosition == 0 && c.YPosition == 0, "Position is not 0,0 for contentless holder");
            Assert.IsTrue(c.SGNodeList.Count == 0, "Count of number of items in SG node list is not zero!");
        }

        [TestMethod]
        public void VisualHolderSingleImage()
        {
            FileInfo f = new FileInfo("..\\..\\..\\t_DTBuilderLib\\file1.jpg");
            VisualHolder_Accessor c = new VisualHolder_Accessor();
            VisualSingleImage single = new VisualSingleImage(f, 600);
            c.AddImage(single);
            Assert.IsTrue(c.Width == single.Width, "Image is width is not right");
            Assert.IsTrue(c.Height == single.Height, "Image height is not right");
            Assert.IsTrue(c.XPosition == 0, "X POsition is not right");
            Assert.IsTrue(c.YPosition == 0, "Y Position is not right");
            var data1 = c.SGNodeList;
            Assert.IsTrue(data1.Count == 1, "Count of SG node list is not right!");
            Assert.IsTrue(data1[0].FileName == f.FullName, "File name of SG node is not right");
            Assert.IsTrue(data1[0].x == 0, "SG x position is not right");
            Assert.IsTrue(data1[0].y == 0, "SG y position is not right");

            c.Scale(0.5F);
            Assert.IsTrue(c.XPosition == 0, "X POsition is not right");
            Assert.IsTrue(c.YPosition == 0, "Y Position is not right");
            Assert.IsTrue(c.Width == 5.0F, "Image is width is not right");
            Assert.IsTrue(c.Height == 7.5F/2.0F, "Image height is not right");
            var data2 = c.SGNodeList;
            Assert.IsTrue(data2[0].x == 0, "SG x position is not right");
            Assert.IsTrue(data2[0].y == 0, "SG y position is not right");

            c.XPosition = 1.0F;
            c.YPosition = 2.0F;
            Assert.IsTrue(c.XPosition == 1, "X POsition is not right");
            Assert.IsTrue(c.YPosition == 2, "Y Position is not right");
            Assert.IsTrue(c.Width == 5.0F, "Image is width is not right");
            Assert.IsTrue(c.Height == 7.5F / 2.0F, "Image height is not right");
            var data3 = c.SGNodeList;
            Assert.IsTrue(data3[0].x == 1.0F, "SG x position is not right");
            Assert.IsTrue(data3[0].y == 2.0F, "SG y position is not right");
        }

        [TestMethod]
        public void VisualHolderOffsetSingleImage()
        {
            FileInfo f = new FileInfo("..\\..\\..\\t_DTBuilderLib\\file1.jpg");
            VisualHolder_Accessor c = new VisualHolder_Accessor();
            VisualSingleImage single = new VisualSingleImage (f, 600);
            single.XPosition = 1.0F;
            single.YPosition = 2.0F;
            c.AddImage(single);
            Assert.IsTrue(c.XPosition == 1.0, "X POsition is not right");
            Assert.IsTrue(c.YPosition == 2.0, "Y Position is not right");
            c.Scale(0.5F);
            Assert.IsTrue(c.XPosition == 1.0, "X POsition is not right");
            Assert.IsTrue(c.YPosition == 2.0, "Y Position is not right");
            Assert.IsTrue(c.Width == 5.0F, "Image is width is not right");
            Assert.IsTrue(c.Height == 7.5F / 2.0F, "Image height is not right");
            var data = c.SGNodeList;
            Assert.IsTrue(data[0].x == 1.0, "SG x position is not right");
            Assert.IsTrue(data[0].y == 2.0, "SG y position is not right");
        }

        [TestMethod]
        public void VisualHolderTwoImages()
        {
            FileInfo f = new FileInfo("..\\..\\..\\t_DTBuilderLib\\file1.jpg");
            VisualHolder_Accessor c = new VisualHolder_Accessor();
            VisualSingleImage single1 = new VisualSingleImage(f, 600);
            double delta = single1.Width;
            VisualSingleImage single2 = new VisualSingleImage(f, 600);

            single2.XPosition = delta;
            c.AddImage(single1);
            c.AddImage(single2);

            Assert.IsTrue(c.XPosition == 0, "X position is not right");
            Assert.IsTrue(c.YPosition == 0, "Y position is not right");
            Assert.IsTrue(c.Width == 20, "Width is not right");
            Assert.IsTrue(c.Height == 7.5, "Height is not right");
            var data1 = c.SGNodeList;
            Assert.IsTrue(data1.Count == 2, "Count of SG node list is not right!");
            Assert.IsTrue(data1[0].x == 0, "SG x of image 1 is not right");
            Assert.IsTrue(data1[0].y == 0, "SG y of image 1 is not right");
            Assert.IsTrue(data1[1].x == delta, "SG x of image 2 is not right");
            Assert.IsTrue(data1[1].y == 0, "SG y of image 2 is not right");

            float factor = 0.5F;
            c.Scale(factor);
            Assert.IsTrue(c.XPosition == 0, "Scaled X pos is not right");
            Assert.IsTrue(c.YPosition == 0, "Sacled Y pos is not right");
            Assert.IsTrue(c.Width == 10F, "Scaled width is not right");
            Assert.IsTrue(c.Height == 7.5F/2.0F, "Scaled height is not right");
            var data2 = c.SGNodeList;
            Assert.IsTrue(data1[0].x == 0, "SG x of image 1 is not right after scale");
            Assert.IsTrue(data1[0].y == 0, "SG y of image 1 is not right after scale");
            Assert.IsTrue(data1[1].x == delta*factor, "SG x of image 2 is not right after scale");
            Assert.IsTrue(data1[1].y == 0, "SG y of image 2 is not right after scale");

            c.XPosition = 3.0F;
            c.YPosition = 2.0F;
            Assert.IsTrue(c.XPosition == 3F, "Moved X pos is not right");
            Assert.IsTrue(c.YPosition == 2F, "Moved Y pos is not right");
            Assert.IsTrue(c.Width == 10F, "Moved width is not right");
            Assert.IsTrue(c.Height == 7.5F/2.0F, "Moved height is not right");
            var data3 = c.SGNodeList;
            Assert.IsTrue(data1[0].x == 3.0F, "SG x of image 1 is not right after scale");
            Assert.IsTrue(data1[0].y == 2.0F, "SG y of image 1 is not right after scale");
            Assert.IsTrue(data1[1].x == 3.0F + delta * factor, "SG x of image 2 is not right after scale");
            Assert.IsTrue(data1[1].y == 2.0F, "SG y of image 2 is not right after scale");
        }

        [TestMethod]
        public void VisualHolderRescaleToOne()
        {
            FileInfo f = new FileInfo("..\\..\\..\\t_DTBuilderLib\\file1.jpg");
            VisualHolder_Accessor c = new VisualHolder_Accessor();
            VisualSingleImage single1 = new VisualSingleImage(f, 600);
            double delta = single1.Width;
            VisualSingleImage single2 = new VisualSingleImage(f, 600);

            single2.XPosition = delta;
            c.AddImage(single1);
            c.AddImage(single2);

            double maxx = c.Width;
            double maxy = c.Height;
            double max = maxx;
            if (maxy > maxx)
                max = maxy;
            c.Scale(1.0F / max);
            double factor = 1.0F / max;

            var data = c.SGNodeList;
            Assert.IsTrue(data[0].x == 0, "SG x position is not right");
            Assert.IsTrue(data[0].y == 0, "SG y position is not right");
            Assert.IsTrue((data[1].x - delta * factor) < 0.001, "SG x position of image 1 is not right");
            Assert.IsTrue(data[1].y == 0, "SG y position of image 1 is not right");
        }

        [TestMethod]
        public void VisualHolderNested()
        {
            FileInfo f = new FileInfo("..\\..\\..\\t_DTBuilderLib\\file1.jpg");
            VisualHolder_Accessor c1 = new VisualHolder_Accessor();
            VisualHolder c2 = new VisualHolder();
            VisualSingleImage single1 = new VisualSingleImage(f, 600);
            VisualSingleImage single2 = new VisualSingleImage(f, 600);

            c1.AddImage(single1);
            c2.AddImage(single2);
            c1.AddImage(c2);

            Assert.IsTrue(c1.SGNodeList.Count == 2, "Count of nested images is not right!");
            Assert.IsTrue(c1.Width == 10F, "Width of nested images is not right");
            Assert.IsTrue(c1.Height == 7.5F, "Height of nested images is not right");

            Assert.IsTrue(c1.SGNodeList[0].ZOrder == 1, "First item does not have zorder 1!");
            Assert.IsTrue(c1.SGNodeList[1].ZOrder == 1, "Second item should have zorder 2!");
            c1.IncZIndex(2);
            Assert.IsTrue(c1.SGNodeList[0].ZOrder == 3, "First item does not have zorder 3!");
            Assert.IsTrue(c1.SGNodeList[1].ZOrder == 3, "Second item should have zorder 4!");
        }

        [TestMethod]
        public void TestImageEnumerator()
        {
            FileInfo f = new FileInfo("..\\..\\..\\t_DTBuilderLib\\file1.jpg");

            VisualSingleImage s1 = new VisualSingleImage(f, 600);
            VisualSingleImage s2 = new VisualSingleImage(f, 600);

            VisualHolder h = new VisualHolder();
            h.AddImage(s1);
            h.AddImage(s2);
            
            Assert.AreEqual(2, h.Count());
        }

        [TestMethod]
        public void TestImageEnumeratorNotDeep()
        {
            FileInfo f = new FileInfo("..\\..\\..\\t_DTBuilderLib\\file1.jpg");

            VisualSingleImage s1 = new VisualSingleImage(f, 600);
            VisualSingleImage s2 = new VisualSingleImage(f, 600);

            VisualHolder h = new VisualHolder();
            VisualHolder h1 = new VisualHolder();

            h1.AddImage(s1);
            h1.AddImage(s2);
            h1.IsCompositionUnit = true;
            h.AddImage(h1);

            VisualSingleImage s3 = new VisualSingleImage(f, 600);
            VisualSingleImage s4 = new VisualSingleImage(f, 600);
            h.AddImage(s3);
            h.AddImage(s4);

            Assert.AreEqual(3, h.Count(), "Expected three images out since we don't go deep into the list of images here!");
        }

        [TestMethod]
        public void TestHierEnumeratorAllFalse()
        {
            FileInfo f = new FileInfo("..\\..\\..\\t_DTBuilderLib\\file1.jpg");

            VisualSingleImage s1 = new VisualSingleImage(f, 600);
            VisualSingleImage s2 = new VisualSingleImage(f, 600);

            VisualHolder h = new VisualHolder();
            h.AddImage(s1);
            h.AddImage(s2);

            Assert.AreEqual(2, h.GetHierarchicalEnumerator(v => v.IsCompositionUnit == true).Count(), "Should have found two images when looking for a true");
            Assert.AreEqual(1, h.GetHierarchicalEnumerator(v => v.IsCompositionUnit == false).Count(), "Should have found only one image when looking for false");
        }

        [TestMethod]
        public void TestHierEnumeratorMixed()
        {
            FileInfo f = new FileInfo("..\\..\\..\\t_DTBuilderLib\\file1.jpg");

            VisualSingleImage s1 = new VisualSingleImage(f, 600);
            VisualSingleImage s2 = new VisualSingleImage(f, 600);

            VisualHolder h = new VisualHolder();
            VisualHolder h1 = new VisualHolder();

            h1.AddImage(s1);
            h1.AddImage(s2);
            h1.IsCompositionUnit = true;
            h.AddImage(h1);

            VisualSingleImage s3 = new VisualSingleImage(f, 600);
            VisualSingleImage s4 = new VisualSingleImage(f, 600);
            h.AddImage(s3);
            h.AddImage(s4);

            Assert.AreEqual(3, h.GetHierarchicalEnumerator(v => v.IsCompositionUnit).Count(), "Didn't find three visuals when I did the mixed counting");
        }

        [TestMethod]
        public void TestZIndex()
        {
            VisualHolder h = new VisualHolder();
            Assert.AreEqual(1, h.ZIndex, "Empty visual guy should have index of zero!");
            h.IncZIndex();
            Assert.AreEqual(1, h.ZIndex, "Empty dude can't be inc'ed!");

            VisualBitmapImage bmi = new VisualBitmapImage(1.0, 1.0, 100, Color.Red);
            bmi.IncZIndex();
            bmi.IncZIndex();
            h.AddImage(bmi);

            Assert.AreEqual(3, h.ZIndex, "Single image should grant its zindex to visual holder");

            VisualBitmapImage bmii = new VisualBitmapImage(1.0, 1.0, 100, Color.Red);
            bmii.IncZIndex();
            h.AddImage(bmii);

            Assert.AreEqual(2, h.ZIndex, "Multiple images - lowest shoudl grant vh its zindex");
        }
    }
}
